#include <cstdio>
const int N = 100005, M = 500005;
int n, m;
int dfn[N], low[N], tot, sum, dcc[N], in[N];
bool bridge[M << 1];

int cnt = 1, heads[N];
struct Edge {
	int u, v, nxt;
} e[M << 1];

inline void add(int u, int v) {
	e[++cnt].v = v;
	e[cnt].u = u;
	e[cnt].nxt = heads[u];
	heads[u] = cnt;
}
inline int min(int a, int b) { return a < b ? a : b; }
void tarjan(int x, int inbri) {
	low[x] = dfn[x] = ++tot;
	for (int i = heads[x]; i; i = e[i].nxt) {
		int v = e[i].v;
		if (!dfn[v]) {
			tarjan(v, i);
			low[x] = min(low[x], low[v]);
			if (low[v] > dfn[x]) { bridge[i] = bridge[i ^ 1] = true; }
		} else if (i != (inbri ^ 1))
			low[x] = min(low[x], dfn[v]);
	}
}
bool vis[N];
void dfs(int x) {
	dcc[x] = sum, vis[x] = true;
	for (int i = heads[x]; i; i = e[i].nxt) {
		int v = e[i].v;
		if (!vis[v] && !bridge[i]) { dfs(v); }
	}
}
int main() {
#ifndef ONLINE_JUDGE
#ifdef LOCAL
	freopen("testdata.in", "r", stdin);
	freopen("testdata.out", "w", stdout);
#endif
#ifndef LOCAL
	freopen("road.in", "r", stdin);
	freopen("road.out", "w", stdout);
#endif
#endif

	scanf("%d%d", &n, &m);
	int a, b;
	for (int i = 1; i <= m; ++i) {
		scanf("%d%d", &a, &b);
		add(a, b);
		add(b, a);
	}
	int ans = 0;
	tarjan(1, 0);
	for (int i = 1; i <= n; ++i) {
		if (!vis[i]) {
			++sum;
			dfs(i);
		}
	}
	for (int i = 2; i <= (m << 1) + 1; i += 2) {
		if (dcc[e[i].v] != dcc[e[i].u]) ++in[dcc[e[i].v]], ++in[dcc[e[i].u]];
	}
	for (int i = 1; i <= sum; ++i) {
		if (in[i] == 1) ++ans;
	}
	printf("%d", (ans + 1) >> 1);
	return 0;
}